﻿// <copyright file="CsvReader.cs" company="The University of Scranton"> 
// Copyright (c) 2010 All Rights Reserved, http://sdpmt.codeplex.com 
// 
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY  
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
// PARTICULAR PURPOSE. 
// 
// </copyright> 
// <author>Luke Benedict</author> 
// <email>luke.benedict@ieee.org</email> 
// <date>2010-11-04</date> 
// <summary>Contains a class that provides functionality to read CSV files output by Bugzilla</summary>
namespace Sdpmt.Filereader
{
    #region Namespace Usage

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel;

    #endregion
    
    /// <summary>
    /// A class that provides functionality to read CSV files output by Bugzilla
    /// </summary>
    public class CsvReader
    {
        #region Public Methods

        /// <summary>
        /// Reads data from a file at the specified path, for date range specified by minDate and maxDate.
        /// </summary>
        /// <param name="path">Path to the file containing defect data</param>
        /// <param name="minDate">The begin date for the data that you want to read</param>
        /// <param name="maxDate">The end data for the data that you want to read</param>
        /// <returns>A SortedDictionary that is the defect data</returns>
        public static System.Collections.Generic.SortedDictionary<DateTime, double> Read(string path, DateTime minDate, DateTime maxDate, BackgroundWorker bw)
        {
            System.Globalization.CultureInfo provider;
            System.Collections.Generic.SortedDictionary<DateTime, double> countDictionary;
            string line;
            string dateField;
            DateTime myDate;
            DateTime curDate;
            TimeSpan len;
            
            provider = System.Globalization.CultureInfo.InvariantCulture;

            
            countDictionary = new SortedDictionary<DateTime, double>();            

            // Use a stream to read the file at the specified path.  FileAccess is set to Read so not to put a lock on the file
            using (System.IO.Stream s = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                // Use a TextReader created from a StreamReader, created from the Stream
                using (System.IO.TextReader t = new System.IO.StreamReader(s))
                {                
                    
                    // While there is something to read...read.
                    while ((line = t.ReadLine()) != null)
                    {
                        // Report process in terms of percent of lines read
                        bw.ReportProgress((int)(100*((float)s.Position / (float)s.Length)));
                        
                        if (line.Contains('['))
                        {
                            dateField = line.Substring(line.IndexOf('[') + 1, line.IndexOf(']') - line.IndexOf('[') - 1);
                        }
                        else
                        {
                            dateField = line.Substring(line.IndexOf(',') + 1, (line.Length - line.IndexOf(',') - 1));
                            dateField = dateField.Replace('"', ' ');
                        }

                        try
                        {
                            myDate = DateTime.Parse(dateField);
                            myDate = new DateTime(myDate.Year, myDate.Month, myDate.Day);
                        }
                        catch (FormatException)
                        {
                            continue;
                        }

                        // Uncomment to switch to month mode
                        // myDate = new DateTime(myDate.Year, myDate.Month, 1);

                        if (myDate > maxDate || myDate < minDate)
                        {
                            continue;
                        }

                        if (countDictionary.ContainsKey(myDate))
                        {
                            countDictionary[myDate]++;

                        }
                        else
                        {
                            countDictionary.Add(myDate, 1);
                        }


                    }
                }
            }


            // Now normalize.

            curDate = minDate;

            len = maxDate - minDate;


            for (int k = 0; k < len.Days; k++)
            {

                float pct = ((float)k / (float)len.Days) * 100;

                int pct2 = (int)pct;
                
                bw.ReportProgress(pct2);

                if (!countDictionary.ContainsKey(curDate))
                {
                    countDictionary.Add(curDate, 0);
                }

                curDate = curDate.AddDays(1);

            }


            System.Collections.Generic.KeyValuePair<DateTime, double>[] clone = new KeyValuePair<DateTime, double>[countDictionary.Count];

            countDictionary.CopyTo(clone, 0);

            foreach (KeyValuePair<DateTime, double> kvp in clone)
            {
                if (!(kvp.Equals(countDictionary.First())))
                {
                    countDictionary[kvp.Key] = countDictionary[kvp.Key] + countDictionary[kvp.Key.AddDays(-1)];
                }
            }


            return countDictionary;

        }

        #endregion

    }//end class

}//end namespace
